/*
 * Copyright 2009 Armando Blancas
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package tests.taskgraph.tasks.data;

import java.io.IOException;

import junit.framework.Assert;
import junit.framework.JUnit4TestAdapter;

import org.junit.Test;

import taskgraph.channels.BooleanChannel;
import taskgraph.channels.ByteChannel;
import taskgraph.channels.Channel;
import taskgraph.channels.DoubleChannel;
import taskgraph.channels.FloatChannel;
import taskgraph.channels.IntChannel;
import taskgraph.channels.LongChannel;
import taskgraph.channels.ShortChannel;
import taskgraph.ports.BooleanOutputPort;
import taskgraph.ports.ByteOutputPort;
import taskgraph.ports.DoubleOutputPort;
import taskgraph.ports.FloatOutputPort;
import taskgraph.ports.InputPort;
import taskgraph.ports.IntOutputPort;
import taskgraph.ports.LongOutputPort;
import taskgraph.ports.OutputPort;
import taskgraph.ports.ShortOutputPort;
import taskgraph.tasks.data.WriteNativeArray;

public class WriteNativeArrayTest {

	/**
	 * Runs the test suite in this class from the command line.
	 * 
	 * @param args	Arguments are ignored.
	 */
	public static void main(String[] args) {
		org.junit.runner.JUnitCore.runClasses(WriteNativeArrayTest.class);
	}
	
	/**
	 * Provides compatibility with 3.x versions of JUnit.
	 * 
	 * @return A 3.x-compatible test suite.
	 */
	public static junit.framework.Test suite() {
		return new JUnit4TestAdapter(WriteNativeArrayTest.class);
	}
	
	/*+----------------------------------------------------------------------+
	  |                                                                      | 
	  | Test the constructors.                                               | 
	  |                                                                      | 
	  +----------------------------------------------------------------------+*/
	
	@Test
	public void defaultConstructor() {
		WriteNativeArray task = new WriteNativeArray();
		Assert.assertNotNull(task);
	}
	
	@Test
	public void defaultInstanceClass() {
		WriteNativeArray task = new WriteNativeArray();
		Assert.assertEquals(WriteNativeArray.class, task.getClass());
	}

	@Test
	public void constructorWithPort() {
		Channel<Object> channel = new Channel<Object>();
		InputPort<Object> input = channel.getInputPort();
		WriteNativeArray task = new WriteNativeArray(input);
		Assert.assertNotNull(task);
	}
	
	@Test
	public void constructorWithPortAndClass() {
		Channel<Object> channel = new Channel<Object>();
		InputPort<Object> input = channel.getInputPort();
		WriteNativeArray task = new WriteNativeArray(input);
		Assert.assertEquals(WriteNativeArray.class, task.getClass());
	}

    /*+----------------------------------------------------------------------+
	  |                                                                      | 
	  | Test the run method.                                                 | 
	  |                                                                      | 
	  +----------------------------------------------------------------------+*/
	
	@Test
	public void testRunBoolean() throws IOException {
		boolean[] data = { false, true, true, false, true, false, false, true };
		boolean[] result = new boolean[data.length];
		
		BooleanChannel channel = new BooleanChannel();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort(), result);
		BooleanOutputPort port = channel.getOutputPort();
		for (boolean b : data) port.write(b);
		port.close();
		
		task.run();
		result = task.getBooleanArray();
		
		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunBooleanWrapper() throws IOException {
		boolean[] data = { false, true, true, false, true, false, false, true };

		Channel<Object> channel = new Channel<Object>();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort());
		OutputPort<Object> port = channel.getOutputPort();
		for (boolean b : data) port.write(b);
		port.close();

		task.setBooleanArray(data);
		task.run();
		boolean[] result = task.getBooleanArray();

		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunByte() throws IOException {
		byte[] data = { 2, 4, 8, 16, 32, 64, 127, 64, 32, 16, 8, 4, 2 };
		byte[] result = new byte[data.length];
		
		ByteChannel channel = new ByteChannel();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort(), result);
		ByteOutputPort port = channel.getOutputPort();
		for (byte b : data) port.write(b);
		port.close();
		
		task.run();
		result = task.getByteArray();
		
		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunByteWrapper() throws IOException {
		byte[] data = { 2, 4, 8, 16, 32, 64, 127, 64, 32, 16, 8, 4, 2 };

		Channel<Object> channel = new Channel<Object>();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort());
		OutputPort<Object> port = channel.getOutputPort();
		for (byte b : data) port.write(b);
		port.close();

		task.setByteArray(data);
		task.run();
		byte[] result = task.getByteArray();

		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunShort() throws IOException {
		short[] data = { 102, 2004, 8500, 1667, 3221, 2112, 5005, 999, 666 };
		short[] result = new short[data.length];
		
		ShortChannel channel = new ShortChannel();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort(), result);
		ShortOutputPort port = channel.getOutputPort();
		for (short s : data) port.write(s);
		port.close();
		
		task.run();
		result = task.getShortArray();
		
		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunShortWrapper() throws IOException {
		short[] data = { 102, 2004, 8500, 1667, 3221, 2112, 5005, 999, 666 };

		Channel<Object> channel = new Channel<Object>();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort());
		OutputPort<Object> port = channel.getOutputPort();
		for (short s : data) port.write(s);
		port.close();

		task.setShortArray(data);
		task.run();
		short[] result = task.getShortArray();

		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunInt() throws IOException {
		int[] data = { 102700, 2004212, 12228500, 166700, 121, 99999, 666000 };
		int[] result = new int[data.length];
		
		IntChannel channel = new IntChannel();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort(), result);
		IntOutputPort port = channel.getOutputPort();
		for (int i : data) port.write(i);
		port.close();
		
		task.run();
		result = task.getIntArray();
		
		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunIntWrapper() throws IOException {
		int[] data = { 102700, 2004212, 12228500, 166700, 121, 99999, 666000 };

		Channel<Object> channel = new Channel<Object>();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort());
		OutputPort<Object> port = channel.getOutputPort();
		for (int i : data) port.write(i);
		port.close();

		task.setIntArray(data);
		task.run();
		int[] result = task.getIntArray();

		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunLong() throws IOException {
		long[] data = { 1027005656540L, 200421210000L, 12228500400L, 16670000L};
		long[] result = new long[data.length];
		
		LongChannel channel = new LongChannel();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort(), result);
		LongOutputPort port = channel.getOutputPort();
		for (long l : data) port.write(l);
		port.close();
		
		task.run();
		result = task.getLongArray();
		
		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunLongWrapper() throws IOException {
		long[] data = { 1027005656540L, 200421210000L, 12228500400L, 16670000L};

		Channel<Object> channel = new Channel<Object>();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort());
		OutputPort<Object> port = channel.getOutputPort();
		for (long l : data) port.write(l);
		port.close();

		task.setLongArray(data);
		task.run();
		long[] result = task.getLongArray();

		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunFloat() throws IOException {
		float[] data = { 102700.56540F, 200.1210000F, 1222.850040F, 1.6670000F};
		float[] result = new float[data.length];
		
		FloatChannel channel = new FloatChannel();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort(), result);
		FloatOutputPort port = channel.getOutputPort();
		for (float f : data) port.write(f);
		port.close();
		
		task.run();
		result = task.getFloatArray();
		
		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunFloatWrapper() throws IOException {
		float[] data = { 102700.56540F, 200.1210000F, 1222.850040F, 1.6670000F};

		Channel<Object> channel = new Channel<Object>();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort());
		OutputPort<Object> port = channel.getOutputPort();
		for (float f : data) port.write(f);
		port.close();

		task.setFloatArray(data);
		task.run();
		float[] result = task.getFloatArray();

		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

	@Test
	public void testRunDouble() throws IOException {
		double[] data = { 102700.56540, 200.12100009, 1222.850040, 1.667000011};
		double[] result = new double[data.length];
		
		DoubleChannel channel = new DoubleChannel();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort(), result);
		DoubleOutputPort port = channel.getOutputPort();
		for (double d : data) port.write(d);
		port.close();
		
		task.run();
		result = task.getDoubleArray();
		
		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}

	}

	@Test
	public void testRunDoubleWrapper() throws IOException {
		double[] data = { 102700.56540, 200.12100009, 1222.850040, 1.667000011};

		Channel<Object> channel = new Channel<Object>();
		WriteNativeArray task = new WriteNativeArray(channel.getInputPort());
		OutputPort<Object> port = channel.getOutputPort();
		for (double d : data) port.write(d);
		port.close();

		task.setDoubleArray(data);
		task.run();
		double[] result = task.getDoubleArray();

		for (int i = 0; i < data.length; ++i) {
			Assert.assertEquals(data[i], result[i]);
		}
	}

    /*+----------------------------------------------------------------------+
	  |                                                                      | 
	  | Negative tests for constructors.                                     | 
	  |                                                                      | 
	  +----------------------------------------------------------------------+*/

	@Test(expected=IllegalArgumentException.class)
	public void constructorWithNullOutputPort() throws IOException {
		new WriteNativeArray(null);
	}

    /*+----------------------------------------------------------------------+
	  |                                                                      | 
	  | Negative tests.                                                      | 
	  |                                                                      | 
	  +----------------------------------------------------------------------+*/

}
